#include "../logs/log.h"

void bench(const std::string& name, size_t thr_cnt, size_t msg_cnt, size_t msg_len)
{
    //获取指定日志器
    log::Logger::ptr logger = log::getLogger(name);
    if(logger.get() == nullptr)
    {
        return ;
    }
    std::cout << "测试信息,信息条数: " << msg_cnt << " 条, 总大小: " << (msg_cnt * msg_len) / 1024 << " kb" << std::endl;
    //构建指定长度的消息
    std::string msg(msg_len - 1, 'A'); //留一个位置给'\n'
    size_t thr_run_cnt = msg_cnt / thr_cnt; //每个线程要跑的信息数
    //std::vector<double> costs(thr_cnt); //记录各个线程的耗时
    double max_cost = 0.0; //总耗时,在多线程中是并发跑的,所以耗时最久的即为总耗时
    //创建指定数量的线程
    std::vector<std::thread> threads;
    for(int i = 0; i < thr_cnt; ++i)
    {
        threads.emplace_back([&, i](){
            auto begin = std::chrono::high_resolution_clock::now(); //获取测试开始时间
            //开始循环写日志
            for(int j = 0; j < thr_run_cnt; ++j)
            {
                logger->FATAL("%s", msg.c_str());
            }
            auto end = std::chrono::high_resolution_clock::now(); //获取测试结束时间
            std::chrono::duration<double> cost = end - begin; //耗时
            //costs[i] = cost.count();
            max_cost = max_cost < cost.count() ? cost.count() : max_cost;
            std::cout << "线程 " << i << " 执行 " << thr_run_cnt << " 条信息耗时 " << cost.count() << " s" << std::endl; 
        });
    }

    //回收线程
    for(int i = 0; i < thr_cnt; ++i)
    {
        threads[i].join();
    }

    //double max_cost = costs[0]; //总耗时,在多线程中是并发跑的,所以耗时最久的即为总耗时
    // for(int i = 0; i < thr_cnt; ++i)
    // {
    //     max_cost = max_cost > costs[i] ? max_cost : costs[i];
    // }

    size_t msg_per_sec = msg_cnt / max_cost; //每秒钟输出的信息数
    size_t size_per_sec = (msg_cnt * msg_len) / (max_cost * 1024); //每秒输出日志大小,单位kb

    std::cout << "总耗时: " << max_cost << " s" << std::endl;
    std::cout << "每秒钟输出的信息数: " << msg_per_sec << " 条" << std::endl;
    std::cout << "每秒钟输出的日志大小: " << size_per_sec << " kb" << std::endl;
} 

void sync_bench()
{
    std::unique_ptr<log::LoggerBuilder> builder(new log::GlobalLoggerBuiler());
    builder->BuilderType(log::SYNC_LOGGER);
    builder->BuilderName("sync_logger");
    builder->BuilderFormat("%m%n");
    builder->BuilderSink<log::FileSink>("./sync_file.log");
    builder->Build();

    //bench("sync_logger", 1, 1000000, 100);
    bench("sync_logger", 3, 1000000, 100);
}

void async_bench()
{
    std::unique_ptr<log::LoggerBuilder> builder(new log::GlobalLoggerBuiler());
    builder->BuilderType(log::ASYNC_LOGGER);
    builder->BuilderName("async_logger");
    builder->BuilderFormat("%m%n");
    builder->BuilderSink<log::FileSink>("./async_file.log");
    builder->Build();

    //bench("async_logger", 1, 1000000, 100);
    bench("async_logger", 3, 1000000, 100);
}

int main()
{
    //sync_bench();
    async_bench();
    return 0;
}